package main

import (
	"context"
	"flag"
	. "gitee.com/aldrice/monitor/configs"
	"gitee.com/aldrice/monitor/internal/monitor"
	"gitee.com/aldrice/monitor/internal/registry"
	"gitee.com/aldrice/monitor/pkg/logging"
	"gitee.com/aldrice/monitor/routers"
	"go.uber.org/zap"
	"mime"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"
)

import (
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// init logger
	logger := logging.Logger().Named("boot")
	//goland:noinspection GoUnhandledErrorResult
	defer logger.Sync()

	// load config
	cfgPath := flag.String("config", "./config.toml", "path to config file (TOML)")
	flag.Parse()
	if err := LoadToml(*cfgPath); err != nil {
		logger.Fatal("load config failed", zap.Stringp("path", cfgPath), zap.Error(err))
	}

	// init log file
	{
		if err := os.MkdirAll(Config.Path.Log, 0775); err != nil {
			logger.Fatal("init log dir failed", zap.Error(err))
		}
		errorFile := filepath.Join(Config.Path.Log, "error.log")
		debugFile := filepath.Join(Config.Path.Log, "debug.log")
		if err := logging.SetLogFile(errorFile, debugFile); err != nil {
			logger.Fatal("init log file failed", zap.Error(err))
		}
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()

	// init db/orm
	if err := registry.InitEnt(ctx); err != nil {
		logger.Fatal("init db/orm failed", zap.Error(err))
	}
	defer func() {
		_ = registry.Ent().Close()
	}()

	// init influxdb
	if err := registry.InitInfluxdb(); err != nil {
		logger.Fatal("init influxdb failed", zap.Error(err))
	}
	defer (*registry.GetClient()).Close()

	// init the MQ structure instance
	if err := registry.InitRabbitMQ(); err != nil {
		logger.Fatal("init the MQ structure instance failed", zap.Error(err))
	}
	// 开启数据处理模块
	err := registry.GetDataProcessMQ().ConsumeSimple(&monitor.DataProcessModule{})
	if err != nil {
		logger.Fatal("fail to start data process service", zap.Error(err))
	}
	// 开启邮件发送模块
	err = registry.GetSendEmailMQ().ConsumeSimple(&monitor.SendEmail{})
	if err != nil {
		logger.Fatal("fail to start mail delivery service", zap.Error(err))
	}
	defer func() {
		_ = registry.GetDataProcessMQ().Destory()
		_ = registry.GetSendEmailMQ().Destory()
	}()

	// init monitor receiver, start accept msg come from monitor-agent
	// will create safe connection if configs defined
	rpcSrv, err := monitor.InitReceiver(Config.TLS.SafeConnection)
	if err != nil {
		logger.Fatal("init monitor failed", zap.Error(err))
	}

	// config & start http server
	r := routers.ApiRouter()
	go func() {
		// todo: temporary fix on windows: https://github.com/golang/go/issues/32350
		_ = mime.AddExtensionType(".js", "application/javascript")

		if err := r.Start(Config.Listen.Http); err != http.ErrServerClosed {
			logger.Fatal("start http server failed", zap.Error(err))
		}
	}()

	// Wait for exit and gracefully shutdown
	{
		osSignals := make(chan os.Signal, 1)
		signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM)
		<-osSignals

		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()
		// gracefully shutdown http service
		if err := r.Shutdown(ctx); err != nil {
			logger.Fatal("gracefully shutdown http service failed", zap.Error(err))
		}
		logger.Info("gracefully shutdown http service succeed")

		// gracefully shutdown gRPC service
		rpcSrv.GracefulStop()
		logger.Info("gracefully shutdown rpc service succeed")

		close(osSignals)
	}
}
